import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:kq_flutter_widgets/widgets/chart/kq_chart_bar_model.dart';
import 'package:kq_flutter_widgets/widgets/chart/kq_chart_line.dart';
import '../../resources/kq_theme_colors.dart';
import 'base/kq_chart_method.dart';
import 'base/kq_chart_model.dart';
import 'kq_chart_line_model.dart';
import 'package:path_drawing/path_drawing.dart';

class KqChartBar extends StatefulWidget {
  ///内部参数设置
  final KqChartBarModel chartModel;

  ///控住多图刷新的key，同一页面有多个图是必填
  final String? keyTag;

  ///背景色
  final Color? backGroundColor;

  ///总高度
  final double? height;

  ///总宽度
  final double? width;

  final List<List<ChartBarValue>>? barList;
  final List<List<ChartLineValue>>? lineList;

  const KqChartBar(
      {Key? key,
      required this.chartModel,
      this.keyTag,
      this.backGroundColor,
      this.height,
      this.width,
      this.barList,
      this.lineList})
      : super(key: key);

  @override
  State<KqChartBar> createState() => _KqChartBarState();
}

class _KqChartBarState extends State<KqChartBar>
    with SingleTickerProviderStateMixin {
  late Animation<double> animation;
  late AnimationController controller;
  late KqChartBarModel barModel;

  @override
  void initState() {
    super.initState();
    barModel = Get.put(widget.chartModel, tag: widget.keyTag);
    barModel.setValueList(widget.barList ?? widget.chartModel.chartBarArray,
        lineList: widget.lineList ?? widget.chartModel.chartLineArray);
    controller = AnimationController(
      duration: barModel.chartModel.duration,
      vsync: this,
    );
    animation = Tween(begin: 0.0, end: 1.0).animate(controller)
      ..addListener(() {
        barModel.chartModel.animationTime = animation.value;
        barModel.update();
      })
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          barModel.chartModel.isAnimationEnd = true;
          barModel.update();
        }
      });
    //启动动画(正向执行)
  }

  KqBarChartPainter getBarChart() {
    KqChartModel model = barModel.chartModel;
    KqBarChartPainter painter = KqBarChartPainter(
        model: model,
        maxY: barModel.maxHeight,
        lines: barModel.chartLineArray,
        bars: barModel.chartBarArray,
        xList: barModel.xList,
        xValue: barModel.xValue,
        yList: barModel.yList,
        yValue: barModel.yValue,
        barColors: barModel.barColors,
        lineColors: barModel.lineColors,
        avgYPointList: barModel.avgYPointList,
        animationTime: model.animationTime,
        isAnimationEnd: barModel.chartModel.isAnimationEnd);
    return painter;
  }

  @override
  Widget build(BuildContext context) {
    barModel.chartModel.isAnimationEnd = false;
    controller.forward(from: 0);
    barModel.setValueList(widget.barList ?? widget.chartModel.chartBarArray,
        lineList: widget.lineList ?? widget.chartModel.chartLineArray);
    KqChartModel item = barModel.chartModel;
    return Container(
      width: widget.width,
      height: widget.height,
      color: widget.backGroundColor,
      child: RepaintBoundary(
          child: Stack(
        children: [
          GetBuilder<KqChartBarModel>(
            init: barModel,
            tag: widget.keyTag,
            builder: (controller) => CustomPaint(
              size: Size(item.sizeWidth, item.sizeHeight),
              foregroundPainter:
                  widget.backGroundColor != null ? getBarChart() : null,
              painter: widget.backGroundColor == null ? getBarChart() : null,
              child: widget.backGroundColor != null
                  ? Container(
                      alignment: Alignment.center,
                      width: item.sizeWidth,
                      height: item.sizeWidth,
                    )
                  : null,
            ),
          ),
          Padding(
            padding: EdgeInsets.only(
                left: item.xLeft!,
                top: item.yTop!,
                right: item.xRight!,
                bottom: item.yBottom!),
            child: SizedBox(
              width: barModel.xWidth,
              height: barModel.yHeight,
              child: GestureDetector(
                onPanDown: (details) {
                  if (!item.isShowValue) {
                    if (item.isShowClickValue) {
                      if (barModel.chartLineArray != null) {
                        for (List<ChartLineValue> list
                            in barModel.chartLineArray!) {
                          for (ChartLineValue info in list) {
                            double x = info.xPoint - item.xLeft!;
                            double y = info.yPoint - item.yTop!;
                            if ((x - 10 < details.localPosition.dx &&
                                    x + 10 > details.localPosition.dx) &&
                                (y - 10 < details.localPosition.dy &&
                                    y + 10 > details.localPosition.dy)) {
                              info.isShow = true;
                            } else {
                              info.isShow = false;
                            }
                          }
                        }
                      }
                    }
                    barModel.update();
                  }
                },
                onPanUpdate: (details) {
                  if (!item.isShowValue) {
                    if (item.isShowSlideValue) {
                      if (barModel.chartLineArray != null) {
                        for (List<ChartLineValue> list
                            in barModel.chartLineArray!) {
                          for (ChartLineValue info in list) {
                            double x = info.xPoint - item.xLeft!;
                            if (x - 10 < details.localPosition.dx &&
                                x + 10 > details.localPosition.dx) {
                              info.isShow = true;
                            } else {
                              info.isShow = false;
                            }
                          }
                        }
                      }
                    }
                    barModel.update();
                  }
                },
                onPanEnd: (DragEndDetails e) {},
              ),
            ),
          )
        ],
      )),
    );
  }
}

class KqBarChartPainter extends CustomPainter {
  ///动画是否结束
  final bool isAnimationEnd;

  ///基本数据
  final KqChartModel model;

  ///x轴坐标数组
  final List xList;

  ///y轴坐标数组
  final List yList;

  final List<Color>? barColors;

  final List<Color>? lineColors;

  ///横坐标内容
  List xValue;

  ///纵坐标内容
  List yValue;

  ///最大值
  final double maxY;

  ///平均线坐标
  List<double> avgYPointList;

  ///具体数据
  final List<List<ChartLineValue>>? lines;
  final List<List<ChartBarValue>> bars;

  ///动画进度
  final double animationTime;

  List<List<BarCanvasModel>> barModels = [];
  List<LineCanvasModel> lineModels = [];

  KqBarChartPainter({
    Key? key,
    required this.isAnimationEnd,
    required this.model,
    required this.maxY,
    required this.xList,
    required this.yList,
    required this.xValue,
    required this.yValue,
    required this.animationTime,
    this.lines,
    this.barColors,
    this.lineColors,
    required this.bars,
    required this.avgYPointList,
  }) : super();

  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke;
    KqChartMethod.drawXYAxisPath(
        canvas: canvas,
        paint: paint,
        axisColor: model.axisColor!,
        xList: xList,
        yList: yList,
        xRight: model.xRight!,
        isDivide: model.isDivide,
        dividerColor: model.dividerColor!,
        hintLineSolid: model.hintLineSolid,
        crossShowList: model.crossShowList ?? [],
        yStyle: TextStyle(fontSize: model.yFont, color: model.yColor),
        xStyle: TextStyle(fontSize: model.xFont, color: model.xColor),
        yValue: yValue,
        xValue: xValue,
        yAisTop: model.yAxisTop!,
        initialPointX: model.initialPointX,
        unit: model.unit);
    _initBarPath(canvas);
    if (lines != null && lines!.isNotEmpty) {
      _initLinePath(canvas);
    }
    KqChartMethod.drawAvgLine(
        canvas: canvas,
        paint: paint,
        avgYPointList: avgYPointList,
        isAvg: model.isAvg,
        xList: xList,
        xRight: model.xRight!,
        avgValues: model.avgValues!,
        avgColors: model.avgColors,
        hintAvgLineSolid: model.hintAvgLineSolid,
        initialPointX: model.initialPointX,
        isAvgValue: model.isAvgValue);
  }

  ///计算柱状图path
  void _initBarPath(Canvas canvas) {
    for (int i = 0; i < xList.length; i++) {
      List<BarCanvasModel> barPath = [];
      for (var j = 0; j < bars.length; j++) {
        Path path = Path();
        List<ChartBarValue> barPoints = bars[j];
        ChartBarValue pointModel = barPoints[i];
        path.moveTo(pointModel.xPoint, yList.last);
        path.lineTo(pointModel.xPoint, pointModel.yPoint);
        barPath.add(BarCanvasModel(
          path: KqChartMethod.getAnimationBarPath(
              path, animationTime, isAnimationEnd),
          barWidth: pointModel.barWidth!,
          barColor: pointModel.barColor ??
              (barColors == null ? KqThemeColors.textLightBlue : barColors![j]),
        ));
      }
      barModels.add(barPath);
    }
    _drawBar(canvas);
  }

  ///绘制柱状图以及文案
  void _drawBar(Canvas canvas) {
    if (barModels.isNotEmpty) {
      for (int i = 0; i < barModels.length; i++) {
        List<BarCanvasModel> list = barModels[i];
        for (var j = 0; j < list.length; j++) {
          BarCanvasModel model = list[j];
          canvas.drawPath(
              model.path,
              Paint()
                ..strokeWidth = model.barWidth
                ..color = model.barColor
                ..style = PaintingStyle.stroke);
        }
        // List<ChartBarValue> info = bars[i];
        // for (int n = 0; n < info.length; n++) {
        //   ChartBarValue value = info[n];
        //   if (model.isShowValue) {
        //     var textValue = TextPainter(
        //         textAlign: TextAlign.center,
        //         ellipsis: '.',
        //         maxLines: 1,
        //         text: TextSpan(text: value.yValue, style: value.style),
        //         textDirection: TextDirection.rtl)
        //       ..layout();
        //     textValue.paint(
        //         canvas,
        //         Offset(value.xPoint - textValue.width / 2,
        //             value.yPoint - textValue.height - 6));
        //   } else {
        //     if (value.isShow) {
        //       var textValue = TextPainter(
        //           textAlign: TextAlign.center,
        //           ellipsis: '.',
        //           maxLines: 1,
        //           text: TextSpan(text: value.yValue, style: value.style),
        //           textDirection: TextDirection.rtl)
        //         ..layout();
        //       textValue.paint(
        //           canvas,
        //           Offset(value.xPoint - textValue.width / 2,
        //               value.yPoint - textValue.height - 6));
        //     }
        //   }
        // }
      }
    }
  }

  ///初始化线形图path
  _initLinePath(Canvas canvas) {
    for (int i = 0; i < lines!.length; i++) {
      List<ChartLineValue> points = lines![i];
      Path path = Path();
      if (points.isNotEmpty) {
        if (model.isCurve) {
          path = KqChartMethod.getSmoothLinePath(points);
        } else {
          path.moveTo(points[0].xPoint, points[0].yPoint);
          for (int j = 0; j < points.length; j++) {
            ChartLineValue point = points[j];
            path.lineTo(point.xPoint, point.yPoint);
          }
        }
        List paths = KqChartMethod.getAnimationLinePath(
            path, points, xList, yList, animationTime, isAnimationEnd);
        Path shadowPath = paths[1];
        lineModels.add(LineCanvasModel(
          path: paths.first,
          points: paths.last,
          shadowPaths: shadowPath,
          lineColor:
              lineColors == null ? KqThemeColors.textLightBlue : lineColors![i],
          lineWidth: points[i].lineWidth,
          shaderColors: [],
        ));
      }
    }
    _drawLine(canvas);
  }

  ///绘制曲线或者折线以及文案
  void _drawLine(Canvas canvas) {
    if (lineModels.isNotEmpty) {
      for (int i = 0; i < lineModels.length; i++) {
        LineCanvasModel info = lineModels[i];
        canvas.drawPath(
            info.path,
            Paint()
              ..strokeWidth = info.lineWidth
              ..color = info.lineColor
              ..style = PaintingStyle.stroke);
        List<ChartLineValue> item = lines![i];
        for (int n = 0; n < info.points; n++) {
          ChartLineValue value = item[n];
          if (model.isShowPoint) {
            canvas.drawCircle(
                Offset(value.xPoint, value.yPoint),
                model.pointRadius!,
                Paint()
                  ..isAntiAlias = true
                  ..strokeCap = StrokeCap.round
                  ..color = info.lineColor
                  ..strokeWidth = 1
                  ..style = PaintingStyle.fill);
          }
          if (model.isShowValue) {
            var textValue = TextPainter(
                textAlign: TextAlign.center,
                ellipsis: '.',
                maxLines: 1,
                text: TextSpan(text: value.yValue, style: value.style),
                textDirection: TextDirection.rtl)
              ..layout();
            textValue.paint(
                canvas,
                Offset(value.xPoint - textValue.width / 2,
                    value.yPoint - textValue.height - 6));
          } else {
            if (value.isShow) {
              var textValue = TextPainter(
                  textAlign: TextAlign.center,
                  ellipsis: '.',
                  maxLines: 1,
                  text: TextSpan(text: value.yValue, style: value.style),
                  textDirection: TextDirection.rtl)
                ..layout();
              textValue.paint(
                  canvas,
                  Offset(value.xPoint - textValue.width / 2,
                      value.yPoint - textValue.height - 6));
              if (item.first.isCountDivider) {
                var paint = Paint()
                  ..strokeWidth = 1
                  ..style = PaintingStyle.stroke
                  ..color = item.first.dividerColor;
                Path horizontalPath = Path();
                horizontalPath.moveTo(value.xPoint, yList.last);
                horizontalPath.lineTo(value.xPoint, value.yPoint);
                if (model.hintLineSolid) {
                  canvas.drawPath(horizontalPath, paint);
                } else {
                  canvas.drawPath(
                    dashPath(
                      horizontalPath,
                      dashArray:
                          CircularIntervalList<double>(<double>[4.0, 2.0]),
                    ),
                    paint,
                  );
                }
                Path verticalPath = Path();
                verticalPath.moveTo(xList.first, value.yPoint);
                verticalPath.lineTo(value.xPoint, value.yPoint);
                if (model.hintLineSolid) {
                  canvas.drawPath(verticalPath, paint);
                } else {
                  canvas.drawPath(
                    dashPath(
                      verticalPath,
                      dashArray:
                          CircularIntervalList<double>(<double>[4.0, 2.0]),
                    ),
                    paint,
                  );
                }
              }
            }
          }
        }
      }
    }
  }

  @override
  bool shouldRepaint(covariant KqBarChartPainter oldDelegate) {
    return true;
  }
}

class BarCanvasModel {
  ///柱状图路径
  Path path;

  ///柱状图宽度
  double barWidth;

  ///柱状颜色
  Color barColor;

  BarCanvasModel({
    required this.barWidth,
    required this.path,
    required this.barColor,
  });
}
